﻿using System;

using System.Collections.Specialized;
using System.Text;
using System.Globalization;

namespace OAuth.Net.Mobile.Consumer
{


  public class UriBuilder
  {
    // Fields
    private bool m_changed;
    private string m_fragment;
    private string m_host;
    private string m_password;
    private string m_path;
    private int m_port;
    private string m_query;
    private string m_scheme;
    private string m_schemeDelimiter;
    private Uri m_uri;
    private string m_username;

    // Methods
    public UriBuilder()
    {
      this.m_changed = true;
      this.m_fragment = string.Empty;
      this.m_host = "localhost";
      this.m_password = string.Empty;
      this.m_path = "/";
      this.m_port = -1;
      this.m_query = string.Empty;
      this.m_scheme = "http";
      this.m_schemeDelimiter = Uri.SchemeDelimiter;
      this.m_username = string.Empty;
    }

    public UriBuilder(string uri)
    {
      this.m_changed = true;
      this.m_fragment = string.Empty;
      this.m_host = "localhost";
      this.m_password = string.Empty;
      this.m_path = "/";
      this.m_port = -1;
      this.m_query = string.Empty;
      this.m_scheme = "http";
      this.m_schemeDelimiter = Uri.SchemeDelimiter;
      this.m_username = string.Empty;
      Uri uri2 = new Uri(uri, UriKind.RelativeOrAbsolute);
      if (uri2.IsAbsoluteUri)
      {
        this.Init(uri2);
      }
      else
      {
        uri = Uri.UriSchemeHttp + Uri.SchemeDelimiter + uri;
        this.Init(new Uri(uri));
      }
    }

    public UriBuilder(Uri uri)
    {
      this.m_changed = true;
      this.m_fragment = string.Empty;
      this.m_host = "localhost";
      this.m_password = string.Empty;
      this.m_path = "/";
      this.m_port = -1;
      this.m_query = string.Empty;
      this.m_scheme = "http";
      this.m_schemeDelimiter = Uri.SchemeDelimiter;
      this.m_username = string.Empty;
      this.Init(uri);
    }

    public UriBuilder(string schemeName, string hostName)
    {
      this.m_changed = true;
      this.m_fragment = string.Empty;
      this.m_host = "localhost";
      this.m_password = string.Empty;
      this.m_path = "/";
      this.m_port = -1;
      this.m_query = string.Empty;
      this.m_scheme = "http";
      this.m_schemeDelimiter = Uri.SchemeDelimiter;
      this.m_username = string.Empty;
      this.Scheme = schemeName;
      this.Host = hostName;
    }

    public UriBuilder(string scheme, string host, int portNumber)
      : this(scheme, host)
    {
      this.Port = portNumber;
    }

    public UriBuilder(string scheme, string host, int port, string pathValue)
      : this(scheme, host, port)
    {
      this.Path = pathValue;
    }

    public UriBuilder(string scheme, string host, int port, string path, string extraValue)
      : this(scheme, host, port, path)
    {     
        this.Extra = extraValue;     
    }

    private string ConvertSlashes(string path)
    {
      StringBuilder builder = new StringBuilder(path.Length);
      for (int i = 0; i < path.Length; i++)
      {
        char ch = path[i];
        if (ch == '\\')
        {
          ch = '/';
        }
        builder.Append(ch);
      }
      return builder.ToString();
    }

    public override bool Equals(object rparam)
    {
      if (rparam == null)
      {
        return false;
      }
      return this.Uri.Equals(rparam.ToString());
    }

    public override int GetHashCode()
    {
      return this.Uri.GetHashCode();
    }

    private void Init(Uri uri)
    {
      this.m_fragment = uri.Fragment;
      this.m_query = uri.Query;
      this.m_host = uri.Host;
      this.m_path = uri.AbsolutePath;
      this.m_port = uri.Port;
      this.m_scheme = uri.Scheme;
      this.m_schemeDelimiter = ":";
      string userInfo = uri.UserInfo;
      if (!string.IsNullOrEmpty(userInfo))
      {
        int index = userInfo.IndexOf(':');
        if (index != -1)
        {
          this.m_password = userInfo.Substring(index + 1);
          this.m_username = userInfo.Substring(0, index);
        }
        else
        {
          this.m_username = userInfo;
        }
      }
      this.SetFieldsFromUri(uri);
    }

    private void SetFieldsFromUri(Uri uri)
    {
      this.m_fragment = uri.Fragment;
      this.m_query = uri.Query;
      this.m_host = uri.Host;
      this.m_path = uri.AbsolutePath;
      this.m_port = uri.Port;
      this.m_scheme = uri.Scheme;
      this.m_schemeDelimiter = ":";
      string userInfo = uri.UserInfo;
      if (userInfo.Length > 0)
      {
        int index = userInfo.IndexOf(':');
        if (index != -1)
        {
          this.m_password = userInfo.Substring(index + 1);
          this.m_username = userInfo.Substring(0, index);
        }
        else
        {
          this.m_username = userInfo;
        }
      }
    }

    public override string ToString()
    {
      if ((this.m_username.Length == 0) && (this.m_password.Length > 0))
      {
        throw new UriFormatException("net_uri_BadUserPassword");
      }
      if (this.m_scheme.Length != 0)
      {

        this.m_schemeDelimiter = (this.m_host.Length != 0) ? Uri.SchemeDelimiter : ":";

      }
      string str = (this.m_scheme.Length != 0) ? (this.m_scheme + this.m_schemeDelimiter) : string.Empty;
      string[] strArray = new string[] { str, this.m_username, (this.m_password.Length > 0) ? (":" + this.m_password) : string.Empty, (this.m_username.Length > 0) ? "@" : string.Empty, this.m_host, ((this.m_port != -1) && (this.m_host.Length > 0)) ? (":" + this.m_port) : string.Empty, (((this.m_host.Length > 0) && (this.m_path.Length != 0)) && (this.m_path[0] != '/')) ? "/" : string.Empty, this.m_path, this.m_query, this.m_fragment };
      return string.Concat(strArray);
    }

    // Properties
    private string Extra
    {
      set
      {
        if (value == null)
        {
          value = string.Empty;
        }
        if (value.Length > 0)
        {
          if (value[0] == '#')
          {
            this.Fragment = value.Substring(1);
          }
          else
          {
            if (value[0] != '?')
            {
              throw new ArgumentException("value");
            }
            int index = value.IndexOf('#');
            if (index == -1)
            {
              index = value.Length;
            }
            else
            {
              this.Fragment = value.Substring(index + 1);
            }
            this.Query = value.Substring(1, index - 1);
          }
        }
        else
        {
          this.Fragment = string.Empty;
          this.Query = string.Empty;
        }
      }
    }

    public string Fragment
    {
      get
      {
        return this.m_fragment;
      }
      set
      {
        if (value == null)
        {
          value = string.Empty;
        }
        if (value.Length > 0)
        {
          value = '#' + value;
        }
        this.m_fragment = value;
        this.m_changed = true;
      }
    }

    public string Host
    {
      get
      {
        return this.m_host;
      }
      set
      {
        if (value == null)
        {
          value = string.Empty;
        }
        this.m_host = value;
        if ((this.m_host.IndexOf(':') >= 0) && (this.m_host[0] != '['))
        {
          this.m_host = "[" + this.m_host + "]";
        }
        this.m_changed = true;
      }
    }

    public string Password
    {
      get
      {
        return this.m_password;
      }
      set
      {
        if (value == null)
        {
          value = string.Empty;
        }
        this.m_password = value;
      }
    }

    public string Path
    {
      get
      {
        return this.m_path;
      }
      set
      {
        if ((value == null) || (value.Length == 0))
        {
          value = "/";
        }
        this.m_path = this.ConvertSlashes(value);
        this.m_changed = true;
      }
    }


    public int Port
    {
      get
      {
        return this.m_port;
      }
      set
      {
        if ((value < -1) || (value > 0xffff))
        {
          throw new ArgumentOutOfRangeException("value");
        }
        this.m_port = value;
        this.m_changed = true;
      }
    }

    public string Query
    {
      get
      {
        return this.m_query;
      }
      set
      {
        if (value == null)
        {
          value = string.Empty;
        }
        if (value.Length > 0)
        {
          value = '?' + value;
        }
        this.m_query = value;
        this.m_changed = true;
      }
    }

    public string Scheme
    {
      get
      {
        return this.m_scheme;
      }
      set
      {
        if (value == null)
        {
          value = string.Empty;
        }
        int index = value.IndexOf(':');
        if (index != -1)
        {
          value = value.Substring(0, index);
        }
        if (value.Length != 0)
        {
          if (!Uri.CheckSchemeName(value))
          {
            throw new ArgumentException("value");
          }
          value = value.ToLower(CultureInfo.InvariantCulture);
        }
        this.m_scheme = value;
        this.m_changed = true;
      }
    }

    public Uri Uri
    {
      get
      {
        if (this.m_changed)
        {
          this.m_uri = new Uri(this.ToString());
          this.SetFieldsFromUri(this.m_uri);
          this.m_changed = false;
        }
        return this.m_uri;
      }
    }

    public string UserName
    {
      get
      {
        return this.m_username;
      }
      set
      {
        if (value == null)
        {
          value = string.Empty;
        }
        this.m_username = value;
      }
    }
  }



}